package com.mall.common;

import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mall.note.Limit;
import com.mall.utils.R;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.concurrent.TimeUnit;

/**
 * @Package: com.mall.common
 * @author: xiao-chen
 * @Create: 2023/4/13-16:15
 * @Version: v 1.0
 * @Description:
 */
@Slf4j
@Component
public class LimitInterceptor implements HandlerInterceptor {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        log.info("进入限流拦截器！");
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //通过反射拿到自定义注解对象
            Limit note = handlerMethod.getMethodAnnotation(Limit.class);
            if (note == null) {
                return true;
            }
            String limitKey = "LIMIT-" + StpUtil.getLoginId().toString();
            ValueOperations<String, Object> operations = redisTemplate.opsForValue();
            if (!redisTemplate.hasKey(limitKey)) {
                //初始化计数器
                operations.set(limitKey, 1, note.time(), TimeUnit.SECONDS);
            } else if ((int) operations.get(limitKey) < note.count()) {
                //在生命周期内计数器加1
                operations.increment(limitKey);

            } else {
                response.setCharacterEncoding("UTF-8");
                //使用setHeader方法设置浏览器使用UTF-8进行解码
                response.setHeader("Content-Type", "text/html;charset=UTF-8");
                response.getWriter().write(new ObjectMapper().writeValueAsString(R.error("手速太快了")));
                return false;
            }
        }
        return true;
    }

    @Override
    public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
